#!/usr/bin/python2
import subprocess
import signal

code = r""""

(load "~/quicklisp/setup.lisp")
(ql:quickload 'feedcircuit)
(ql:quickload 's-http-server)
(ql:quickload 's-utils)
(ql:quickload 'puri)
(rename-package :s-http-server :sfs)

(defun write-text-response (request stream &optional text)
  (unless text (setf (sfs:get-keep-alive request) nil))
  (sfs:write-http-response-status-line stream)
  (sfs:write-http-response-headers
    (sfs:standard-http-response-headers
      request :content-type "text/plain;charset=utf-8"
      :content-length (when text (file-string-length stream text))) stream)
  (sfs:write-http-response-line "" stream)
  (when text (write-string text stream))
  t)

(defun list-handler (server handler request stream)
  (declare (ignore server))
  (let ((body (format nil "~{~a~^~%~}"
                      (mapcar #'file-namestring
                              (feedcircuit:list-ebooks (second handler))))))
    (write-text-response request stream body)))

(defun sync-handler (server handler request stream)
  (declare (ignore server))
  (write-text-response request stream)
  (let ((config (with-open-file (f (second handler)) (read f)))
        (b-out (make-broadcast-stream stream *standard-output*))
        (b-err (make-broadcast-stream stream *error-output*)))
    (let ((*standard-output* b-out)
          (*error-output* b-err))
      (apply #'feedcircuit:ebook-from-feeds config))))

(defun parse-query (query)
  (flet ((split (str sep) (s-utils:tokens str :separators (list sep)))
         (unescape (str) (puri::decode-escaped-encoding str t nil)))
    (mapcar #'(lambda (param) (mapcar #'unescape (split param #\=)))
            (split query #\&))))

(defun get-urls (query)
  (let ((params (parse-query query)))
    (mapcar #'second
            (remove-if-not #'(lambda (param) (equalp (first param) "url")) params))))

(defun grab-handler (server handler request stream)
  (declare (ignore server))
  (let ((urls (get-urls (puri:uri-query (sfs:get-uri request))))
        (b-out (make-broadcast-stream stream *standard-output*))
        (b-err (make-broadcast-stream stream *error-output*)))
    (let ((*standard-output* b-out)
          (*error-output* b-err))
      (write-text-response request stream)
      (write-string (feedcircuit:ebook-from-urls urls (second handler)) stream))))

(let* ((server (sfs:make-s-http-server :port 8889))
       (config-file "config")
       (config (with-open-file (f config-file) (read f)))
       (work-dir (namestring (merge-pathnames (or (getf config :work-dir) "")))))
  (sfs:register-context-handler server "/sync" #'sync-handler
    :arguments (list config-file))
  (sfs:register-context-handler server "/list" #'list-handler
    :arguments (list work-dir))
  (sfs:register-context-handler server "/grab" #'grab-handler
    :arguments (list work-dir))
  (sfs:register-context-handler server "/" #'sfs:static-resource-handler
    :arguments (list work-dir) :at-end-p t)
  (sfs:start-server server)
  (handler-case (read) (serious-condition ())))

"""

lisp = ["/usr/bin/sbcl", "--noinform", "--disable-ldb", "--lose-on-corruption",
        "--end-runtime-options", "--no-userinit", "--no-sysinit",
        "--disable-debugger", "--noprint", "--end-toplevel-options"]

proc = subprocess.Popen(lisp, stdin=subprocess.PIPE)
proc.stdin.write(code[1:])
proc.stdin.flush()
try:
  proc.wait()
except:
  pass
proc.stdin.close()
